const fs = require('fs'),
exec = require('child_process').exec,
svc = require('../util/service'),
log = require('../util/log'),
uploadDir = __dirname + '/../../m3u8',
winExe = 'D:/ffmpeg/ffmpeg-20170225-7e4f32f-win64-static/bin/ffmpeg.exe',
isWin = !!process.platform.match(/^win/);

var queue = [],
isHandling = false;

module.exports = (req, res) =>
svc.handlePost(req, res, (reqObj, resolve) => {
	_upload(reqObj.audio)
	reqObj.video && _upload(reqObj.video)
	queue.push(reqObj)
	if (!isHandling) {
		handle()
	}
	resolve({
		result: 1
	})
})

function _upload(file) {
	var fileRootName = file.name || (Math.random() * new Date().getTime()).toString(36).replace(/\./g, ''),
	fileExtension = file.type,
	filePathBase = uploadDir + '/',
	fileRootNameWithBase = filePathBase + fileRootName,
	filePath = fileRootNameWithBase + '.' + fileExtension,
	fileID = 2,
	fileBuffer;
	if (!fs.existsSync(uploadDir)) {
		fs.mkdirSync(uploadDir)
	}
	while (fs.existsSync(filePath)) {
		filePath = fileRootNameWithBase + '(' + fileID + ').' + fileExtension;
		fileID += 1;
	}
	file.contents = file.contents.split(',').pop();
	fileBuffer = new Buffer(file.contents, 'base64');
	fs.writeFileSync(filePath, fileBuffer);
	return fileRootName + '.' + fileExtension
}

function handle() {
	if (isHandling) {
		return;
	}
	if (queue.length == 0) {
		isHandling = false;
		return
	}
	isHandling = true;
	var reqObj = queue[0];
	queue = queue.slice(1),
	start_time = new Date().getTime();
	new Promise(resolve => {
		if (!reqObj.video) {
			resolve()
			return
		}
		var videoFile = uploadDir + '/' + reqObj.video.name,
		command;
		if (isWin) {
			command = '"' + winExe + '" -itsoffset -00:00:00 -i "' + uploadDir + '/' + reqObj.audio.name + '" -itsoffset -00:00:00 -i "' + uploadDir + '/' + reqObj.video.name + '" "' + uploadDir + '/' + reqObj.audio.name.split('.')[0] + '-merged.webm"';
		} else {
			command = 'ffmpeg -i ' + uploadDir + '/' + reqObj.audio.name + ' -itsoffset -00:00:01 -i ' + uploadDir + '/' + reqObj.video.name + ' -map 0:0 -map 1:0 ' + uploadDir + '/' + reqObj.audio.name.split('.')[0] + '-merged.webm'
		}
		exec(command, (error, stdout, stderr) => {
			if (error) {
				log(error)
				return
			}
			fs.unlink(uploadDir + '/' + reqObj.audio.name)
			fs.unlink(uploadDir + '/' + reqObj.video.name)
			reqObj.audio.name = reqObj.audio.name.split('.')[0] + '-merged.webm';
			resolve()
		})
	}).then(() => {
		var command;
		if (isWin) {
			command = '"' + winExe + '" -i "' + uploadDir + '/' + reqObj.audio.name + '" "' + uploadDir + '/' + reqObj.audio.name.split('.')[0] + '.mp4"';
		} else {
			command = 'ffmpeg -i ' + uploadDir + '/' + reqObj.audio.name + ' ' + uploadDir + '/' + reqObj.audio.name.split('.')[0] + '.mp4';
		}
		exec(command, (error, stdout, stderr) => {
			if (error) {
				log(error)
				return
			}
			fs.unlink(uploadDir + '/' + reqObj.audio.name)
			reqObj.audio.name = reqObj.audio.name.split('.')[0] + '.mp4';
			if (isWin) {
				command = '"' + winExe + '" -y -i "' + uploadDir + '/' + reqObj.audio.name + '" -vcodec copy -acodec copy -vbsf h264_mp4toannexb "' + uploadDir + '/' + reqObj.audio.name.split('.')[0] + '.ts"';
			} else {
				command = 'ffmpeg -y -i ' + uploadDir + '/' + reqObj.audio.name + ' -vcodec copy -acodec copy -vbsf h264_mp4toannexb ' + uploadDir + '/' + reqObj.audio.name.split('.')[0] + '.ts';
			}
			exec(command, (error, stdout, stderr) => {
				if (error) {
					log(error)
					return
				}
				fs.unlink(uploadDir + '/' + reqObj.audio.name)
				reqObj.audio.name = reqObj.audio.name.split('.')[0] + '.ts';
				var lines = fs.readFileSync(uploadDir + '/test.m3u8', 'utf-8').split('\r\n'),
				newContent = '',
				i = 0;
				for (; i < 4; i++) {
					newContent += lines[i] + '\r\n'
				}
				newContent += lines[i].split(':').shift() + ':' + (parseInt(lines[i].split(':').pop()) + 1) + '\r\n'
				i++
				if (lines.length == 13) {
					fs.unlink(uploadDir + '/' + lines[i + 1])
					i += 2
				}
				for (; i < lines.length; i++) {
					newContent += lines[i] + '\r\n'
				}
				newContent += '#EXTINF:' + reqObj.duration + '\r\n' + reqObj.audio.name
				fs.writeFileSync(uploadDir + '/test.m3u8', newContent)
				log(reqObj.audio.name + ' takes ' + (new Date().getTime() - start_time) + 'ms')
				isHandling = false;
				handle()
			})
		})
	}).catch (err => {
		log(err)
	})
}

function mp4ToTs(mp4, resolve) {
	if (isWin) {
		command = '"' + winExe + '" -y -i "' + uploadDir + '/' + mp4 + '" -vcodec copy -acodec copy -vbsf h264_mp4toannexb "' + uploadDir + '/' + mp4.split('.')[0] + '.ts"';
	} else {
		command = 'ffmpeg -y -i ' + uploadDir + '/' + mp4 + ' -vcodec copy -acodec copy -vbsf h264_mp4toannexb ' + uploadDir + '/' + mp4.split('.')[0] + '.ts';
	}
	exec(command, (error, stdout, stderr) => {
		if (error) {
			log(error)
			return
		}
		fs.unlink(uploadDir + '/' + mp4)
		resolve(mp4.split('.')[0] + '.ts')
	})
}

function updateM3u8(ts) {
	var lines = fs.readFileSync(uploadDir + '/test.m3u8', 'utf-8').split('\r\n'),
	newContent = '',
	i = 0;
	for (; i < 4; i++) {
		newContent += lines[i] + '\r\n'
	}
	newContent += lines[i].split(':').shift() + ':' + (parseInt(lines[i].split(':').pop()) + 1) + '\r\n'
	i++
	if (lines.length == 13) {
		fs.unlink(uploadDir + '/' + lines[i + 1])
		i += 2
	}
	for (; i < lines.length; i++) {
		newContent += lines[i] + '\r\n'
	}
	newContent += '#EXTINF:2\r\n' + ts
	fs.writeFileSync(uploadDir + '/test.m3u8', newContent)
}

function _handle() {
	if (isHandling) {
		return;
	}
	if (queue.length == 0) {
		isHandling = false;
		return
	}
	isHandling = true;
	var mp4 = queue[0];
	queue = queue.slice(1),
	start_time = new Date().getTime();
	new Promise(resolve => {
		mp4ToTs(mp4, ts => {
			updateM3u8()
			isHandling = false;
			handle()
		})
	}).then(() => {}).catch (err => {
		log(err)
	})
}
